﻿using System.Text.Encodings.Web;
using System.Text.Json;
using Azure;
using Azure.AI.OpenAI;
using Microsoft.Extensions.Configuration;

const string help = """
                    将如下文件放置在Sada.AI.Toolbox.GptCaller.exe文件目录下：
                    SystemMessage.txt 给出ChatGPT的系统信息
                    Prompt.jsonl JSON Lines文件，每一行的格式为：{"prompt": "xxxx"}
                    """;

Console.WriteLine(help);
Console.WriteLine();

var systemMessagePath = GetPath("SystemMessage.txt");
if (!File.Exists(systemMessagePath)) {
    Console.WriteLine("错误：找不到SystemMessage.txt");
    return;
}

var promptPath = GetPath("Prompt.jsonl");
if (!File.Exists(promptPath)) {
    Console.WriteLine("错误：找不到Prompt.jsonl");
    return;
}

var promptCompletionPath = GetPath("PromptCompletion.jsonl");
var numberCompletion = 0;

if (File.Exists(promptCompletionPath)) {
    using var completionReader = new StreamReader(promptCompletionPath);
    while (!string.IsNullOrEmpty(completionReader.ReadLine())) {
        numberCompletion++;
    }
}

Console.WriteLine($"已经完成{numberCompletion}个completion。");

var configuration = new ConfigurationBuilder()
    .AddUserSecrets<Program>().Build();
const string ModelId = nameof(ModelId);
const string Endpoint = nameof(Endpoint);
const string ApiKey = nameof(ApiKey);


var azureOpenAIResourceUri = new Uri(configuration[Endpoint]);
var azureOpenAIApiKey = new AzureKeyCredential(configuration[ApiKey]);
var client = new OpenAIClient(azureOpenAIResourceUri, azureOpenAIApiKey);

var systemMessage = File.ReadAllText(systemMessagePath);
using var promptReader = new StreamReader(promptPath);
using var promptWriter = new StreamWriter(promptCompletionPath, true);

string promptJson;
var numberPrompt = 0;
var tokenUsed = 0;
while (!string.IsNullOrEmpty(promptJson = promptReader.ReadLine())) {
    numberPrompt++;
    if (numberPrompt <= numberCompletion) {
        continue;
    }

    if (tokenUsed > 200 * 1000) {
        await Task.Delay(60000);
        tokenUsed = 0;
    }

    var prompt = JsonSerializer.Deserialize<PromptWrapper>(promptJson,
            new JsonSerializerOptions { PropertyNameCaseInsensitive = true })
        .Prompt;
    if (string.IsNullOrWhiteSpace(prompt)) {
        promptWriter.WriteLine(JsonSerializer.Serialize(new {
            Prompt = string.Empty, Exception = string.Empty
        }));
        promptWriter.Flush();
        continue;
    }


    var chatCompletionsOptions = new ChatCompletionsOptions {
        DeploymentName = configuration[ModelId],
        Messages = {
            new ChatRequestSystemMessage(systemMessage),
            new ChatRequestUserMessage(prompt)
        },
        MaxTokens = 500
    };

    string promptCompletionJson;
    try {
        var response =
            await client.GetChatCompletionsAsync(chatCompletionsOptions);
        tokenUsed += response.Value.Usage.TotalTokens;

        var promptCompletion = new {
            Prompt = prompt,
            Completion = response.Value.Choices[0].Message.Content
        };
        promptCompletionJson = JsonSerializer.Serialize(promptCompletion,
            new JsonSerializerOptions {
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            });
    } catch (Exception e) {
        promptCompletionJson = JsonSerializer.Serialize(
            new { Prompt = prompt, Exception = e.Message },
            new JsonSerializerOptions {
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            });
        tokenUsed += 16 * 1000;
    }

    promptWriter.WriteLine(promptCompletionJson);
    promptWriter.Flush();

    Console.WriteLine($"完成{numberPrompt}个completion，消耗{tokenUsed}个Token。");
}

return;

string GetPath(string filename) =>
    Path.Combine(Directory.GetCurrentDirectory(), filename);

class PromptWrapper {
    public string Prompt { get; set; }
}